﻿using System;
using System.Collections.Generic;
using ServiceStack.Caching.Memcached;

namespace Chappie.Infrastructure.Cache
{
    /// <summary>
    /// 基于MemCache的分布式缓存实现(依赖EnyimMemcache客户端及ServiceStackMemCache)
    /// </summary>
    public class MemCacheProvider : ICacheProvider
    {
        private readonly MemcachedClientCache _cache;

        public MemCacheProvider()
        {
            _cache = new MemcachedClientCache();
        }

        #region Implementation of ICacheProvider

        /// <summary>
        /// 添加绝对过期缓存
        /// </summary>
        /// <typeparam name="T">缓存值类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <param name="value">缓存值</param>
        /// <param name="expiresAt">缓存过期绝对时间点</param>
        /// <returns></returns>
        public void Add<T>(string key, T value, DateTime expiresAt)
        {
            _cache.Add(key, value, expiresAt);
        }

        /// <summary>
        /// 添加相对过期缓存
        /// </summary>
        /// <typeparam name="T">缓存值类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <param name="value">缓存值</param>
        /// <param name="expiresIn">缓存过期相对过期时间</param>
        /// <returns></returns>
        public void Add<T>(string key, T value, TimeSpan expiresIn)
        {
            _cache.Add(key, value, expiresIn);
        }

        /// <summary>
        /// 添加永久缓存(有则添加,无则更新)
        /// </summary>
        /// <typeparam name="T">缓存值类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <param name="value">缓存值</param>
        /// <returns></returns>
        public void Set<T>(string key, T value)
        {
            _cache.Set<T>(key, value);
        }

        /// <summary>
        /// 添加绝对过期缓存(有则添加,无则更新)
        /// </summary>
        /// <typeparam name="T">缓存值类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <param name="value">缓存值</param>
        /// <param name="expiresAt">缓存过期绝对时间点</param>
        /// <returns></returns>
        public void Set<T>(string key, T value, DateTime expiresAt)
        {
            _cache.Set<T>(key, value, expiresAt);
        }

        /// <summary>
        /// 添加相对过期缓存(有则添加,无则更新)
        /// </summary>
        /// <typeparam name="T">缓存值类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <param name="value">缓存值</param>
        /// <param name="expiresIn">缓存过期相对过期时间</param>
        /// <returns></returns>
        public void Set<T>(string key, T value, TimeSpan expiresIn)
        {
            _cache.Set<T>(key, value, expiresIn);
        }

        /// <summary>
        /// 批量添加同类型缓存
        /// </summary>
        /// <typeparam name="T">缓存值类型</typeparam>
        /// <param name="values">缓存值</param>
        public void SetMulti<T>(IDictionary<string, T> values)
        {
            _cache.SetAll<T>(values);
        }

        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <typeparam name="T">缓存值类型</typeparam>
        /// <param name="key">缓存键</param>
        /// <returns></returns>
        public T Get<T>(string key)
        {
            return _cache.Get<T>(key);
        }

        /// <summary>
        /// 批量获取同类型缓存
        /// </summary>
        /// <param name="keys">缓存键集合</param>
        /// <returns></returns>
        public IDictionary<string, T> GetAll<T>(IEnumerable<string> keys)
        {
            return _cache.GetAll<T>(keys);
        }

        /// <summary>
        /// 移除缓存
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns></returns>
        public void Remove(string key)
        {
            _cache.Remove(key);
        }

        /// <summary>
        /// 批量移除缓存
        /// </summary>
        /// <param name="keys">缓存键集合</param>
        public void RemoveMulti(IEnumerable<string> keys)
        {
            _cache.RemoveAll(keys);
        }

        /// <summary>
        /// 判断缓存是否存在
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>存在返回Ture,不存在返回Flase</returns>
        public bool Exists(string key)
        {
            return _cache.Get(key) != null;
        }

        /// <summary>
        /// 清空所有缓存对象
        /// </summary>
        public void Flush()
        {
            _cache.FlushAll();
        }

        #endregion
    }
}